/*
Javier Kohen's Java Framework Classes.
Copyright (C) 2000  Javier Kohen <jkohen at tough.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package ar.com.jkohen.awt;

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

import ar.com.jkohen.util.Resources;
import ar.com.jkohen.irc.MircMessage;

public class TextFieldHistory extends TextField implements ActionListener, KeyListener
{
	private static Frame frame;
	private static Resources res;
	private static TextAttributePicker pa;

	private boolean focusTraversable;

    // Purge entries past this number (actual entry is part of the count.)
	// Twenty seems a sane number for a human being's short-term memory of what he could've written =)
	// Forty either, because memory works better at night
    private int history_max_size = 40;

    private Vector history;
    private int pos;

    public TextFieldHistory(Frame f)
	{
		this(0);
		this.frame = f;
    }

    public TextFieldHistory(int columns)
	{
		this("", columns);
    }

    public TextFieldHistory(String text)
	{
		this(text, 0);
    }

    public TextFieldHistory(String text, int columns)
	{
		super(text, columns);

		// First place is for the current entry's content.
		history = new Vector(1);
		history.addElement("");
		pos = 0;

		addActionListener(this);
		addKeyListener(this);
    }

    public int getMaximumHistorySize()
	{
		return history_max_size;
    }

    public void setMaximumHistorySize(int new_size)
	{
		history_max_size = new_size;
		history.setSize(history_max_size);
    }

    private void loadItem(int n)
	{
		String item = (String) history.elementAt(pos);
		setText(item);
		setCaretPosition(item.length());
    }

	public void insert(String new_text)
	{
    	int i = getSelectionStart();
		int j = getSelectionEnd();
		String text = getText();

		if (i == j)
		{
			// Insert attributes at caret position.
            int pos = getCaretPosition();

            text = text.substring(0, pos).concat(new_text).concat(text.substring(pos));

            setText(text);
            setCaretPosition(pos + new_text.length());
		}
		else
		{
			// Insert attributes at start and at end of selection.
			text = text.substring(0, i).concat(new_text).concat(text.substring(i, j)).concat(new_text).concat(text.substring(j));

			setText(text);
			setSelectionStart(i);
			setSelectionEnd(j + (new_text.length() * 2));
		}
	}

	public void pickAttr()
	{
		if (pa == null)
		{
			Dimension disposition = new Dimension(16, 1);
			Dimension item_size = new Dimension(12, 16);
			Dimension gap = new Dimension(2, 2);
			pa = new TextAttributePicker(frame, this, disposition, item_size, gap);

			// WORKAROUND: #34 something is broken in NN.
			pa.addWindowListener(new WindowAdapter()
			{
				public void windowClosed(WindowEvent e)
				{
			    	pa = null;
				}

	            public void windowClosing(WindowEvent windowevent)
	            {
	                windowevent.getWindow().dispose();
	            }
		    });
		}
		else
		{
			pa.setTextField(this);
			pa.show();
		}
    }

    public void actionPerformed(ActionEvent e)
	{
		// Record entered lines.
		String entry = e.getActionCommand();

		if (entry.length() == 0)
		    return;

		// Reset history position.
		pos = 0;

		history.insertElementAt(e.getActionCommand(), 1);

		if (history.size() > history_max_size)
			history.setSize(history_max_size);
    }

	public void keyPressed(KeyEvent ev)
	{
		if (!this.isEditable())
			return;

		if (ev.getModifiers() == KeyEvent.CTRL_MASK)
		{
			switch (ev.getKeyCode())
			{
    		case (KeyEvent.VK_P):
				pickAttr();
    		    break;

    		case (KeyEvent.VK_O):
    			insert(String.valueOf(MircMessage.RESET));
    			break;

    		case (KeyEvent.VK_B):
    			insert(String.valueOf(MircMessage.BOLD));
    			break;

    		case (KeyEvent.VK_U):
    			insert(String.valueOf(MircMessage.UNDERLINE));
    			break;

    		case (KeyEvent.VK_I):
    			insert(String.valueOf(MircMessage.ITALIC));
    			break;

    		case (KeyEvent.VK_R):
    			insert(String.valueOf(MircMessage.REVERSE));
    			break;

			case (KeyEvent.VK_G):
    			insert(String.valueOf(MircMessage.BELL));
    			break;
			}
		}
		else
		{
			switch (ev.getKeyCode())
			{
			case KeyEvent.VK_UP:
			    if (pos == 0)
				{
					// Store not yet entered entry.
					history.setElementAt(getText(), 0);
		    	}
		    	pos = (pos + 1) % history.size();
		    	loadItem(pos);
		    	break;

    		case KeyEvent.VK_DOWN:
    		    if (pos == 0)
    			{
    				// Store not yet entered entry.
    				history.setElementAt(getText(), 0);
    				pos = history.size();
    		    }
    		    pos--;
    		    loadItem(pos);
    		    break;

    		case KeyEvent.VK_ESCAPE:
    		    pos = 0;
    			loadItem(pos);
    		    break;

    		default:
    		    pos = 0;
    		    break;
    		}
		}
    }

    public void keyReleased(KeyEvent e)
	{
    }

    public void keyTyped(KeyEvent e)
	{
    }

	public void setFocusTraversable(boolean b)
	{
		this.focusTraversable = b;
	}
/*
	public boolean isFocusTraversable()
	{
		return(focusTraversable);
	}
*/
	public void transferFocus()
	{

	}
}
